package com.xxj.duck.core;

import java.util.ArrayList;
import java.util.Random;

import javax.microedition.khronos.opengles.GL10;

import org.anddev.andengine.collision.BaseCollisionChecker;
import org.anddev.andengine.entity.layer.ILayer;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.Scene.IOnAreaTouchListener;
import org.anddev.andengine.entity.scene.Scene.ITouchArea;
import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.entity.sprite.AnimatedSprite.IAnimationListener;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.text.ChangeableText;
import org.anddev.andengine.entity.text.Text;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.util.GLHelper;

import android.content.SharedPreferences;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.badlogic.gdx.math.Vector2;
import com.xxj.duck.DuckGame;
import com.xxj.duck.R;
import com.xxj.duck.core.entity.Cloud;
import com.xxj.duck.core.entity.Duck;
import com.xxj.duck.core.entity.Feather;

// Game Main UI (Menu & playing UI)
public class Game {

	private int GAME_STATE;
	public static final int STATE_MENU = 0;
	public static final int STATE_RUN = 1;
	public static final int STATE_DIALOGS = 2;

	private Random random = new Random();

	private ArrayList<Duck> ducks = new ArrayList<Duck>();
	private ArrayList<Duck> ducksToRemove = new ArrayList<Duck>();
	private ArrayList<Feather> feathers = new ArrayList<Feather>();
	private ArrayList<Feather> feathersBuffer = new ArrayList<Feather>();
	private ArrayList<Feather> feathersToRemove = new ArrayList<Feather>();

	private ArrayList<Cloud> clouds = new ArrayList<Cloud>();
	private int maxClouds = 5;

	private Sprite grass;
	private Sprite hills;
	private Sprite sky;
	private Sprite barrel;
	private Sprite flash;
	private Sprite shot;
	private Sprite aim;
	private Sprite pauseButton;

	private float aimXSpeed = 0;
	private float aimYSpeed = 0;

	private int shells = 3;
	private boolean updateShells = false;
	private ArrayList<Sprite> shellSprites = new ArrayList<Sprite>();

	private boolean roundOver = false;

	private int ducksKilled = 0;
	private int ducksCreated = 0;
	private final int ducksCount = 20;
	private final int ducksToNextLevel = 16;

	// the margin size that meet the screen top or left
	final int marginSize = 5;

	private Double score = 0.0;
	private float birdSpeed = 2.0f;
	private Text scoreLabel;
	private Text highScoreLabel;
	private Text nextLevelMsg;
	private ChangeableText scoreText;
	private ChangeableText highScoreText;
	private ChangeableText ducksToNextLevelText;
	private ChangeableText ducksText;
	private ChangeableText currLvlText;
	private int currentLevel = 1;

	private Scene gameScene;
	public final DuckGame gameActivity;

	// menu section
	private Sprite logo;
	private Sprite startButton;
	private Sprite scoresButton;
	private Sprite settingsButton;
	private boolean loadComplete = false;
	boolean useSound;
	boolean useVibro;

	private boolean paused = false;

	public Game(final Scene gameScene, final DuckGame ctx) {
		this.gameScene = gameScene;
		this.gameActivity = ctx;

		GAME_STATE = STATE_MENU;

		this.initGameScene();
	}

	private void initGameScene() {

		this.initGameLayer0();
		this.initGameLayer1();
		this.initGameLayer2();
		this.initGameLayerTop();

		this.displaySpritesForMenu();

		DuckGame.music.setLooping(true);
		if (gameActivity.getSharedPreferences(DuckGame.SP_PREFS_NAME, 0)
				.getBoolean(DuckGame.SP_USE_SOUND, true)) {
			DuckGame.music.play();
		}
	}

	private void initGameLayerTop() {
		// create game menu on top layer
		logo = new Sprite(DuckGame.WIDTH / 2 - DuckGame.logo.getWidth() / 2,
				DuckGame.HEIGHT / 2 - DuckGame.logo.getHeight() / 2
						- DuckGame.startButton.getHeight() / 2, DuckGame.logo);
		ILayer topLayer = gameScene.getTopLayer();
		topLayer.addEntity(logo);

		startButton = new Sprite(
				DuckGame.WIDTH
						/ 2
						- (DuckGame.startButton.getWidth()
								+ DuckGame.settingsButton.getWidth() + DuckGame.scoresButton.getWidth())
						/ 2, logo.getY() + logo.getHeight() + 20,
				DuckGame.startButton);
		topLayer.addEntity(startButton);
		gameScene.registerTouchArea(startButton);// touch

		scoresButton = new Sprite(startButton.getX() + startButton.getWidth()
				+ 5, logo.getY() + logo.getHeight() + 20, DuckGame.scoresButton);
		topLayer.addEntity(scoresButton);
		gameScene.registerTouchArea(scoresButton);// touch

		settingsButton = new Sprite(scoresButton.getX()
				+ scoresButton.getWidth() + 5, logo.getY() + logo.getHeight()
				+ 20, DuckGame.settingsButton);
		topLayer.addEntity(settingsButton);
		gameScene.registerTouchArea(settingsButton);// touch

		// add touch handler for game menu (these buttons)
		gameScene.setOnAreaTouchListener(new IOnAreaTouchListener() {
			@Override
			public boolean onAreaTouched(final TouchEvent sceneTouchEvent,
					ITouchArea touchArea, float touchAreaLocalX,
					float touchAreaLocalY) {
				if (!loadComplete) {
					return true;
				}
				return touchHandler(sceneTouchEvent, touchArea);
			}
		});
	}

	private void initGameLayer2() {
		// create grass
		grass = new Sprite(0, DuckGame.HEIGHT - DuckGame.grass.getHeight(),
				DuckGame.grass.getWidth(), DuckGame.grass.getHeight(),
				DuckGame.grass);
		ILayer layer2 = gameScene.getLayer(2);
		layer2.addEntity(grass);

		// create barrel & shot
		flash = new Sprite(DuckGame.WIDTH / 2 - DuckGame.flash.getWidth() / 2,
				DuckGame.HEIGHT - DuckGame.flash.getHeight() / 2,
				DuckGame.flash.getWidth(), DuckGame.flash.getHeight(),
				DuckGame.flash);
		flash.setAlpha(0.0f);
		layer2.addEntity(flash);

		shot = new Sprite(DuckGame.WIDTH / 2 - DuckGame.shot.getWidth() / 2,
				DuckGame.HEIGHT - DuckGame.shot.getHeight() / 2,
				DuckGame.shot.getWidth(), DuckGame.shot.getHeight(),
				DuckGame.shot);
		shot.setAlpha(0.0f);
		layer2.addEntity(shot);

		// create crosshair
		aim = new Sprite(DuckGame.WIDTH / 2 - DuckGame.aim.getWidth() / 2,
				DuckGame.HEIGHT / 2 - DuckGame.aim.getHeight() / 2,
				DuckGame.aim.getWidth(), DuckGame.aim.getHeight(), DuckGame.aim);
		layer2.addEntity(aim);

		barrel = new Sprite(
				DuckGame.WIDTH / 2 - DuckGame.barrel.getWidth() / 2,
				DuckGame.HEIGHT - DuckGame.barrel.getHeight() / 2,
				DuckGame.barrel.getWidth(), DuckGame.barrel.getHeight(),
				DuckGame.barrel);
		layer2.addEntity(barrel);

		// create pause button
		pauseButton = new Sprite(DuckGame.WIDTH
				- DuckGame.pauseButton.getWidth() * 1.5f, DuckGame.HEIGHT
				- DuckGame.pauseButton.getHeight() * 1.4f,
				DuckGame.pauseButton.getWidth(),
				DuckGame.pauseButton.getHeight(), DuckGame.pauseButton);
		layer2.addEntity(pauseButton);
		gameScene.registerTouchArea(pauseButton);// touch
	}

	private void initGameLayer1() {
		// create hills
		hills = new Sprite(0, DuckGame.HEIGHT - DuckGame.hills.getHeight(),
				DuckGame.hills.getWidth(), DuckGame.hills.getHeight(),
				DuckGame.hills) {
			protected void onInitDraw(final GL10 pGL) {
				super.onInitDraw(pGL);
				GLHelper.enableTextures(pGL);
				GLHelper.enableTexCoordArray(pGL);
				GLHelper.enableDither(pGL);
			}
		};

		ILayer layer1 = gameScene.getLayer(1);
		layer1.addEntity(hills);
		// create score & level & duck count
		layer1.addEntity(highScoreLabel = new Text(25, 5, DuckGame.font,
				getString(R.string.high_score)));
		layer1.addEntity(highScoreText = new ChangeableText(highScoreLabel
				.getX() + highScoreLabel.getWidth() + 20, 5, DuckGame.font,
				gameActivity.gameScore.getHighGameScore()));

		layer1.addEntity(scoreLabel = new Text(25,
				highScoreLabel.getHeight() + 10, DuckGame.font,
				getString(R.string.score)));
		layer1.addEntity(scoreText = new ChangeableText(scoreLabel.getX()
				+ scoreLabel.getWidth() + 10, highScoreLabel.getHeight() + 10,
				DuckGame.font, "000000000000"));
		scoreText.setText("0");

		//
		layer1.addEntity(ducksToNextLevelText = new ChangeableText(
				DuckGame.WIDTH, 5, DuckGame.font, "0000000"));
		layer1.addEntity(ducksText = new ChangeableText(DuckGame.WIDTH, 5,
				DuckGame.font, "0000000"));
		layer1.addEntity(currLvlText = new ChangeableText(DuckGame.WIDTH, 5,
				DuckGame.font, "0000000"));
		this.updateTextPosForLeft();

		layer1.addEntity(nextLevelMsg = new Text(0, 0, DuckGame.font,
				getString(R.string.next_level)));
		nextLevelMsg.setPosition(DuckGame.WIDTH / 2 - nextLevelMsg.getWidth()
				/ 2, DuckGame.HEIGHT / 2 - nextLevelMsg.getHeight() / 2);
		nextLevelMsg.setAlpha(1.0f);
		this.updateShellsIndicator();
	}

	private void initGameLayer0() {
		ILayer layer0 = gameScene.getLayer(0);
		// create sky
		sky = new Sprite(0, 0, DuckGame.sky.getWidth(),
				DuckGame.sky.getHeight(), DuckGame.sky) {
			protected void onInitDraw(final GL10 pGL) {
				super.onInitDraw(pGL);
				GLHelper.enableTextures(pGL);
				GLHelper.enableTexCoordArray(pGL);
				GLHelper.enableDither(pGL);
			}
		};
		layer0.addEntity(sky);

		// create clouds
		for (int i = 0; i < maxClouds; i++) {
			Cloud cloud;
			float cloudSpeed = 1;

			switch (1 + random.nextInt(3)) {
			default:
				cloud = new Cloud(random.nextInt(700), random.nextInt(160),
						DuckGame.largeCloud.getWidth(),
						DuckGame.largeCloud.getHeight(), DuckGame.largeCloud);
				cloudSpeed = (10 + random.nextInt(5)) / 10f; // 1.0 - 1.5
				break;
			case 2:
				cloud = new Cloud(random.nextInt(700), random.nextInt(120),
						DuckGame.mediumCloud.getWidth(),
						DuckGame.mediumCloud.getHeight(), DuckGame.mediumCloud);
				cloudSpeed = (5 + random.nextInt(5)) / 10f; // 0.5 - 1.0
				break;
			case 3:
				cloud = new Cloud(random.nextInt(700), random.nextInt(80),
						DuckGame.smallCloud.getWidth(),
						DuckGame.smallCloud.getHeight(), DuckGame.smallCloud);
				cloudSpeed = (1 + random.nextInt(4)) / 10f; // 0.1 - 0.5
				break;
			}

			cloud.setCloudSpeed(cloudSpeed);
			clouds.add(cloud);
			layer0.addEntity(cloud);
		}
	}

	// set text and position for [duck left] and [game level].
	private void updateTextPosForLeft() {

		float x = DuckGame.WIDTH - currLvlText.getWidth() * 1.4f;

		currLvlText.setText(getString(R.string.gameLevel) + currentLevel);
		currLvlText.setPosition(x, marginSize);

		ducksToNextLevelText.setText(getString(R.string.ducksToNextLevelLeft)
				+ (ducksToNextLevel - ducksKilled));
		ducksToNextLevelText.setPosition(x,
				currLvlText.getY() + currLvlText.getHeight() + marginSize);

		ducksText.setText(getString(R.string.ducksKilled) + ducksKilled);
		ducksText.setPosition(x, ducksToNextLevelText.getY()
				+ ducksToNextLevelText.getHeight() + marginSize);
	}

	private String getString(int id) {
		return gameActivity.getResources().getString(id);
	}

	private boolean touchHandler(final TouchEvent sceneTouchEvent,
			ITouchArea touchArea) {
		int action = sceneTouchEvent.getAction();
		if (action != MotionEvent.ACTION_DOWN) {
			return true;
		}
		if (startButton.isVisible() && touchArea.equals(startButton)) {
			this.startGame();
		} else if (pauseButton.isVisible() && touchArea.equals(pauseButton)
				&& !paused) {
			this.exitOrPauseGame();
		} else if (settingsButton.isVisible()
				&& touchArea.equals(settingsButton)) {
			this.showSettingUI();
		} else if (scoresButton.isVisible() && touchArea.equals(scoresButton)) {
			gameActivity.gameScore.showScoreUI();
		}
		return true;
	}

	private void startGame() {
		if (gameActivity.findViewById(R.id.settingsDialog).getVisibility() == View.GONE
				&& gameActivity.findViewById(R.id.backMenuDialog)
						.getVisibility() == View.GONE
				&& gameActivity.findViewById(R.id.scoreRankDialog).getVisibility() == View.GONE) {

			GAME_STATE = STATE_RUN;

			this.displaySpritesForRun();

			nextLevel(true);
			paused = false;

			// save game settings with SharedPreferences (not
			// SQLite)
			SharedPreferences settings = gameActivity.getSharedPreferences(
					DuckGame.SP_PREFS_NAME, 0);
			useSound = settings.getBoolean(DuckGame.SP_USE_SOUND, true);
			useVibro = settings.getBoolean(DuckGame.SP_USE_VIBRO, true);
		}
	}

	private void displaySpritesForMenu() {
		this.displaySprites(true, false);
	}

	private void displaySpritesForRun() {
		this.displaySprites(false, true);
	}

	private void displaySprites(boolean isShowGameMenu, boolean isShowGameRun) {

		// if isShowGameRun is true, should display these sprites for game
		// running UI.
		barrel.setVisible(isShowGameRun);
		aim.setVisible(isShowGameRun);
		flash.setVisible(isShowGameRun);
		shot.setVisible(isShowGameRun);

		currLvlText.setVisible(isShowGameRun);
		ducksText.setVisible(isShowGameRun);
		ducksToNextLevelText.setVisible(isShowGameRun);

		scoreLabel.setVisible(isShowGameRun);
		scoreText.setVisible(isShowGameRun);
		highScoreLabel.setVisible(isShowGameRun);
		highScoreText.setVisible(isShowGameRun);

		pauseButton.setVisible(isShowGameRun);
		for (Sprite shell : shellSprites) {
			shell.setVisible(isShowGameRun);
		}

		// if isShowGameMenu is true, should display these sprites for game menu
		// UI.
		logo.setVisible(isShowGameMenu);
		startButton.setVisible(isShowGameMenu);
		settingsButton.setVisible(isShowGameMenu);
		scoresButton.setVisible(isShowGameMenu);

	}

	private void showSettingUI() {
		gameActivity.runOnUiThread(new Thread() {
			public void run() {
				if (gameActivity.findViewById(R.id.backMenuDialog)
						.getVisibility() == View.GONE
						&& gameActivity.findViewById(R.id.saveScoreDialog)
								.getVisibility() == View.GONE) {

					gameActivity.findViewById(R.id.settingsDialog)
							.setVisibility(View.VISIBLE);

					SharedPreferences settings = gameActivity
							.getSharedPreferences(DuckGame.SP_PREFS_NAME, 0);
					((CheckBox) gameActivity.findViewById(R.id.settSoundEnable))
							.setChecked(settings.getBoolean(
									DuckGame.SP_USE_SOUND, true));
					((CheckBox) gameActivity.findViewById(R.id.settVibroEnable))
							.setChecked(settings.getBoolean(
									DuckGame.SP_USE_VIBRO, true));
				}
			};
		});
	}

	private void makeShoot() {
		if (useSound) {
			DuckGame.sShotReload.play();
		}
		if (useVibro) {
			gameActivity.getEngine().vibrate(100);
		}
		flash.setAlpha(1.0f);

		shot.setPosition(aim.getX() + aim.getWidth() / 2 - shot.getWidth() / 2,
				aim.getY() + aim.getHeight() / 2 - shot.getHeight() / 2);
		shot.setAlpha(1.0f);
		//

		for (final Duck duck : ducks) {
			if (duck.isFlying() && aim.collidesWith(duck)) {
				// >If bullet collides with duck the duck must die.
				// if((bird.getX()+bird.getWidth()*0.2f>shot.getX()+shot.getWidth()
				// && bird.getX()+bird.getWidth()*0.8f <
				// shot.getX()+shot.getWidth()) &&
				// (bird.getY()+bird.getHeight()*0.2f>shot.getY()+shot.getHeight()&&
				// bird.getY()+bird.getHeight()*0.8f <
				// shot.getY()+shot.getHeight()))
				// if(bird.collidesWith(shot))
				float birdCenterX = duck.getX() + duck.getWidth() / 2;
				float birdCenterY = duck.getY() + duck.getHeight() / 2;

				float shotCenterX = shot.getX() + shot.getWidth() / 2;
				float shotCenterY = shot.getY() + shot.getHeight() / 2;

				if (BaseCollisionChecker.checkAxisAlignedRectangleCollision(
						birdCenterX - duck.getWidth() * 0.6f / 2, birdCenterY
								- duck.getHeight() * 0.6f / 2, birdCenterX
								+ duck.getWidth() * 0.6f / 2, birdCenterY
								+ duck.getHeight() * 0.6f / 2,

						shotCenterX - shot.getWidth() * 0.9f / 2, shotCenterY
								- shot.getHeight() * 0.9f / 2, shotCenterX
								+ shot.getWidth() * 0.9f / 2, shotCenterY
								+ shot.getHeight() * 0.9f / 2)) {
					duck.setFalling(true);
					duck.stopAnimation(12);

					// score+=Math.abs((int)(100*bird.getXSpeed()));
					score += ((1 - (duck.timeLeft() / duck.getLifeTime())) * 100f);
					ducksKilled++;

					synchronized (feathersBuffer) {

						for (int i = 0; i < 10; i++) {
							float featherSize = 1 + (1 + random.nextInt(9)) / 10;
							// first duck
							Feather feather;
							if (random.nextBoolean()) {
								feather = new Feather(
										/*-20*/duck.getX()
												- duck.getWidth()
												* featherSize
												/ 2
												+ random.nextInt((int) (duck
														.getWidth())),
										duck.getY()
												- duck.getHeight()
												* featherSize
												/ 2
												+ random.nextInt((int) (duck
														.getHeight()))/*
																	 * random.
																	 * nextInt (
																	 * 320
																	 * -40grass
																	 */,
										DuckGame.feather.getWidth()
												* featherSize,
										DuckGame.feather.getHeight()
												* featherSize, DuckGame.feather);
							} else {
								feather = new Feather(
										/*-20*/duck.getX()
												- duck.getWidth()
												* featherSize
												/ 2
												+ random.nextInt((int) (duck
														.getWidth())),
										duck.getY()
												- duck.getHeight()
												* featherSize
												/ 2
												+ random.nextInt((int) (duck
														.getHeight()))/*
																	 * random.
																	 * nextInt (
																	 * 320
																	 * -40grass
																	 */,
										DuckGame.featherFlipped.getWidth()
												* featherSize,
										DuckGame.featherFlipped.getHeight()
												* featherSize,
										DuckGame.featherFlipped);
							}
							feathersBuffer.add(feather);
							gameScene.getLayer(1).addEntity(feather);
						}
					}

					break;
				} else {
					duck.setWasScared(true);
					duck.animate(new long[] { 100, 100, 100, 100 }, 8, 11, 4,
							new IAnimationListener() {
								public void onAnimationEnd(
										AnimatedSprite animatedSprite) {
									duck.animate(new long[] { 100, 100, 100,
											100 }, 0, 3, true);
								}
							});
				}
			}
		}
		//
		shells--;
		if (shells < 0) {
			shells = 0;
		}
		updateShells = true;

		if (ducks.size() > 0 && shells == 0) {
			roundOver = true;
		}
		//
	}

	public void update() {

		if (!loadComplete) {
			loadComplete = true;
			gameActivity.hideLoadimg(true);
		}

		// update clouds, independed to game started or menu
		for (Cloud cloud : clouds) {
			cloud.update();
		}

		if (GAME_STATE == STATE_RUN && !paused) {
			this.updateForRun();
		} else if (GAME_STATE == STATE_MENU) {
			this.updateForMenu();
		}
	}

	private void updateForMenu() {
		ILayer layer1 = gameScene.getLayer(1);
		if (ducks.size() > 0) {
			for (Duck bird : ducks) {
				layer1.removeEntity(bird);
			}
			ducks.clear();
		}

		if (feathers.size() > 0) {
			for (Feather feather : feathers) {
				layer1.removeEntity(feather);
			}
			feathers.clear();
		}

		if (feathersBuffer.size() > 0) {
			for (Feather feather : feathersBuffer) {
				layer1.removeEntity(feather);
			}
			feathersBuffer.clear();
		}
	}

	private void updateForRun() {

		this.updateCrosshair();
		this.updateFeathers();

		if (updateShells) {
			this.updateShellsIndicator();
			updateShells = false;
		}
		if (ducks.size() == 0) {
			this.createNewDucks();
		} else if (ducksKilled >= ducksToNextLevel) {
			this.nextLevel(false);
		} else if (ducksCreated > ducksCount) {
			this.gameFailed();
		} else {// if (ducks.size() > 0) {
			this.updateDuckState();
		}
	}

	private void gameFailed() {
		GAME_STATE = STATE_DIALOGS;
		for (Feather f : feathers) {
			gameScene.getLayer(1).removeEntity(f);
		}
		feathers.clear();
		gameActivity.runOnUiThread(new Thread() {
			@Override
			public void run() {
				// gameActivity.onShowDialog(DuckGame.DIALOG_LOCAL_GLOBAL_SCORES);
				LinearLayout scoresLayout = (LinearLayout) gameActivity
						.findViewById(R.id.saveScoreDialog);
				scoresLayout.setVisibility(View.VISIBLE);
				TextView scoreTextCtrl = (TextView) scoresLayout
						.findViewById(R.id.scoreText);
				scoreTextCtrl.setText(gameActivity.getResources().getString(
						R.string.wish_to_save_scores)
						+ " (" + score.intValue() + ")");
			}
		});
	}

	private void createNewDucks() {
		// first duck
		Duck duck = new Duck(0, random.nextInt((int) (grass.getY() - grass
				.getHeight())), DuckGame.duckFly.getTileWidth(),
				DuckGame.duckFly.getTileHeight(), DuckGame.duckFly, useSound);

		ducks.add(duck);
		gameScene.getLayer(1).addEntity(duck);
		duck.setXSpeed(birdSpeed);
		// was a bug with flying bird backward :)
		DuckGame.duckFly.setFlippedHorizontal(false);
		duck.animate(new long[] { 100, 100, 100, 100 }, 0, 3, true);

		// second duck flying from another side
		duck = new Duck(
				DuckGame.WIDTH - DuckGame.duckFlyFlipped.getTileWidth(),
				random.nextInt((int) (grass.getY() - grass.getHeight())),
				DuckGame.duckFlyFlipped.getTileWidth(),
				DuckGame.duckFlyFlipped.getTileHeight(),
				DuckGame.duckFlyFlipped, useSound);
		ducks.add(duck);
		duck.setXSpeed(-birdSpeed);
		gameScene.getLayer(1).addEntity(duck);
		DuckGame.duckFlyFlipped.setFlippedHorizontal(true);
		duck.animate(new long[] { 100, 100, 100, 100 }, 0, 3, true);

		shells = 3;
		updateShells = true;

		ducksCreated += 2;

		// >After each level move the field so it gives the illusion
		// of new a new scene.
		// TODO: test it
		// hills.getTextureRegion().setTexturePosition(hills.getTextureRegion().getTexturePositionX()+400,hills.getTextureRegion().getTexturePositionY())
		// ;
		// DuckGame.hills.setTexturePosition(pX, pY);
	}

	private void updateDuckState() {
		for (Duck duck : ducks) {
			if (roundOver && !duck.isFalling() && !duck.isFallen()) {
				duck.setFlyAway(true);

			}

			duck.update();

			if (duck.isFallen()) {
				if (useSound)
					DuckGame.sGroundHit.play();
				ducksToRemove.add(duck);
			}
		}

		roundOver = false;

		for (Duck duck : ducksToRemove) {
			ducks.remove(duck);
			gameScene.getLayer(1).removeEntity(duck);
		}
		ducksToRemove.clear();
	}

	public boolean onKeyDown(int keyCode) {
		if (keyCode == KeyEvent.KEYCODE_BACK
				|| keyCode == KeyEvent.KEYCODE_HOME) {
			gameActivity.runOnUiThread(new Thread() {
				@Override
				public void run() {
					exitOrPauseGame();
				}
			});
			return true;
		}
		return false;
	}

	private void exitOrPauseGame() {
		if (GAME_STATE == STATE_RUN) {
			pauseGame();
			gameActivity.findViewById(R.id.backMenuDialog).setVisibility(
					View.VISIBLE);
			gameActivity.findViewById(R.id.backMenuResumeButton).setVisibility(
					View.GONE);
			gameActivity.findViewById(R.id.backResumeButton).setVisibility(
					View.VISIBLE);
			gameActivity.findViewById(R.id.backMenuButton).setVisibility(
					View.VISIBLE);
		} else {
			gameActivity.findViewById(R.id.backMenuDialog).setVisibility(
					View.VISIBLE);
			gameActivity.findViewById(R.id.backMenuResumeButton).setVisibility(
					View.VISIBLE);
			gameActivity.findViewById(R.id.backResumeButton).setVisibility(
					View.GONE);
			gameActivity.findViewById(R.id.backMenuButton).setVisibility(
					View.GONE);
		}
	}

	// public void onAccelerometerChanged(AccelerometerData accelerometerData) {
	// if (accelerometer) {
	// aimYSpeed = (accelerometerData.getX() - 5) * 2;
	// if (aimYSpeed > 0) {
	// aimYSpeed *= 1.5f;
	// }
	// aimXSpeed = accelerometerData.getY() * 3;
	// }
	// }

	public void updateXYSpeed(float xSpeed, float ySpeed) {
		this.aimXSpeed = xSpeed;
		this.aimYSpeed = ySpeed;
	}

	public void updateShellsIndicator() {
		float shellOffset = 0;

		while (shells < shellSprites.size()) {
			gameScene.getLayer(2).removeEntity(shellSprites.get(0));
			shellSprites.remove(0);
		}

		for (int i = 0; i < shells; i++) {
			Sprite shell;
			if (i + 1 > shellSprites.size()) {
				shell = new Sprite(DuckGame.shell.getWidth() / 2 + shellOffset,
						DuckGame.HEIGHT - DuckGame.shell.getHeight() * 1.5f,
						DuckGame.shell.getWidth(), DuckGame.shell.getHeight(),
						DuckGame.shell);
				gameScene.getLayer(2).addEntity(shell);
				shellSprites.add(shell);
			} else {
				shell = shellSprites.get(i);
				shell.setPosition(DuckGame.shell.getWidth() / 2 + shellOffset,
						shell.getY());
			}

			shellOffset += shell.getWidth();
		}

		scoreText.setText("" + score.intValue());

		this.updateTextPosForLeft();
	}

	public void updateCrosshair() {
		aim.setPosition(aim.getX() + aimXSpeed, aim.getY() + aimYSpeed);

		if (aim.getY() + aim.getHeight() / 2 > grass.getY()) {
			aim.setPosition(aim.getX(), grass.getY() - aim.getHeight() / 2);
		} else if (aim.getY() + aim.getHeight() / 2 < 0) {
			aim.setPosition(aim.getX(), 0 - aim.getHeight() / 2);
		}

		if (aim.getX() + aim.getWidth() / 2 > DuckGame.WIDTH) {
			aim.setPosition(DuckGame.WIDTH - aim.getWidth() / 2, aim.getY());
		} else if (aim.getX() + aim.getWidth() / 2 < 0) {
			aim.setPosition(0 - aim.getWidth() / 2, aim.getY());
		}

		// move barrel au/down in percentage to aim position
		// aimY * (barrel.height*0.2f)/grass.getY/*gameheight-grass height*/
		float barrelYOffset = aim.getY() * (barrel.getHeight() * 0.2f)
				/ grass.getY();

		barrel.setPosition(barrel.getX(), DuckGame.HEIGHT - barrel.getHeight()
				/ 2/*
					 * default position
					 */
				+ barrelYOffset);
		// rotate barrel
		Vector2 src = new Vector2(barrel.getX() + barrel.getWidth() / 2,
				barrel.getY() + barrel.getHeight() / 2);
		Vector2 dst = new Vector2(aim.getX() + aim.getWidth() / 2, aim.getY()
				+ aim.getHeight() / 2);

		float angle = (float) (Math.atan2(src.y - dst.y, src.x - dst.x) * 180
				/ Math.PI - 90);
		barrel.setRotation(angle);

		// barrel shoot flash
		flash.setPosition(
				barrel.getX() + barrel.getWidth() / 2 - flash.getWidth() / 2,
				barrel.getY() - flash.getHeight() / 2);
		flash.setRotationCenter(
		/* DuckGame.CAMERA_WIDTH/2 */flash.getWidth() / 2, barrel.getHeight()
				- flash.getHeight());
		flash.setRotation(barrel.getRotation());

		if (flash.getAlpha() > 0) {
			flash.setAlpha(flash.getAlpha() - 0.4f);
			if (flash.getAlpha() < 0) {
				flash.setAlpha(0);
			}
		}

		if (shot.getAlpha() > 0) {
			shot.setAlpha(shot.getAlpha() - 0.3f);
			if (shot.getAlpha() < 0) {
				shot.setAlpha(0);
			}
		}

		if (nextLevelMsg.getAlpha() > 0) {
			nextLevelMsg.setAlpha(nextLevelMsg.getAlpha() - 0.025f);
			if (nextLevelMsg.getAlpha() < 0) {
				nextLevelMsg.setAlpha(0);
			}
		}
	}

	public void updateFeathers() {
		// should help with concurrent modification exception
		if (feathersBuffer.size() > 0) {
			feathers.addAll(feathersBuffer);
			feathersBuffer.clear();
		}

		if (feathers.size() > 0) {
			for (Feather f : feathers)// done
			{
				if (f != null) {
					f.update();
					// move to delete cache
					if (f.isDead()) {
						feathersToRemove.add(f);
					}
				}
			}
		}

		// remove dead feathers
		if (feathersToRemove.size() > 0) {
			for (Feather f : feathersToRemove) {
				feathers.remove(f);
				// remove from feather layer
				gameScene.getLayer(1).removeEntity(f);
			}
			feathersToRemove.clear();
		}
	}

	public void nextLevel(boolean restart) {
		ducksKilled = 0;
		ducksCreated = 0;
		shells = 3;

		aimXSpeed = aimYSpeed = 0;

		if (restart) {
			birdSpeed = 1f;
			currentLevel = 1;
			score = 0.0;
			aim.setPosition(DuckGame.WIDTH / 2 - DuckGame.aim.getWidth() / 2,
					DuckGame.HEIGHT / 2 - DuckGame.aim.getHeight() / 2);
			this.displaySpritesForRun();
		} else {
			birdSpeed *= 1.11f;
			currentLevel++;
			nextLevelMsg.setAlpha(1.0f);
		}
	}

	public void goToGameOrMenu(boolean returnToGame) {
		if (returnToGame) {
			GAME_STATE = STATE_RUN;
			nextLevel(true);
			paused = false;
		} else {
			GAME_STATE = STATE_MENU;
			this.displaySpritesForMenu();
		}
	}

	public void onTouch(TouchEvent sceneTouchEvent) {
		int action = sceneTouchEvent.getAction();
		if (!paused) {
			if (action == MotionEvent.ACTION_UP && shells > 0) {
				aim.setPosition(sceneTouchEvent.getX() - aim.getWidth() / 2,
						sceneTouchEvent.getY() - aim.getHeight() / 2);
				this.makeShoot();
			} else if (action == MotionEvent.ACTION_MOVE) {
				aim.setPosition(sceneTouchEvent.getX() - aim.getWidth() / 2,
						sceneTouchEvent.getY() - aim.getHeight() / 2);
			}
		}
	}

	public Double getScore() {
		return score;
	}

	public void setLoadComplete(boolean loadComplete) {
		this.loadComplete = loadComplete;
	}

	public void pauseGame() {
		paused = true;
	}

	public void unPauseGame() {
		paused = false;
		// for (Duck bird : ducks) {
		// bird.addPauseTime(System.currentTimeMillis() - startPauseTime);
		// }
	}

	public int getGAME_STATE() {
		return GAME_STATE;
	}

	public boolean isPaused() {
		return paused;
	}
}
